package JavaDesignModel;
// 实验六  透明组合模式

import java.util.ArrayList;
import java.util.List;


// 文件系统组件接口（抽象组件）
// 使用透明组合模式，将叶子节点和复合节点的操作统一声明
// 透明模式的特点：叶子节点和复合节点具有完全一致的接口
interface FileSystemComponent {

//     获取组件名称
//     @return 组件名称
    String getName();

//     获取组件大小
//     对于文件：返回文件实际大小
//     对于文件夹：递归计算文件夹内所有内容的大小
//     @return 组件大小（字节）
    long getSize();

//     添加子组件
//     叶子节点不支持此操作，会抛出异常
//     @param component 要添加的子组件
    void add(FileSystemComponent component);

//     删除子组件
//     叶子节点不支持此操作，会抛出异常
//     @param component 要删除的子组件
    void remove(FileSystemComponent component);

//    获取子组件
//    叶子节点不支持此操作，会抛出异常
//    @param index 子组件索引
//    @return 指定索引的子组件
    FileSystemComponent getChild(int index);

//    显示组件结构
//    @param indent 缩进字符串，用于显示层次结构
    void display(String indent);
}

// JPG图片文件类（叶子节点）
// 叶子节点代表单个文件，没有子组件
class JpgFile implements FileSystemComponent {
    private String name;    // 文件名
    private long size;      // 文件大小

//    构造函数
//    @param name 文件名
//    @param size 文件大小（字节）
    public JpgFile(String name, long size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public long getSize() {
        return size;  // 叶子节点直接返回自身大小
    }

    @Override
    public void add(FileSystemComponent component) {
        // 叶子节点不支持添加操作，抛出异常
        throw new UnsupportedOperationException("叶子节点不支持添加操作");
    }

    @Override
    public void remove(FileSystemComponent component) {
        // 叶子节点不支持删除操作，抛出异常
        throw new UnsupportedOperationException("叶子节点不支持删除操作");
    }

    @Override
    public FileSystemComponent getChild(int index) {
        // 叶子节点没有子节点，抛出异常
        throw new UnsupportedOperationException("叶子节点没有子节点");
    }

    @Override
    public void display(String indent) {
        // 显示图片文件信息，使用相机emoji标识
        System.out.println(indent + "📷 " + name + " (" + size + " bytes)");
    }
}


// 视频文件类（叶子节点）
// 叶子节点代表单个视频文件，没有子组件
class VideoFile implements FileSystemComponent {
    private String name;    // 文件名
    private long size;      // 文件大小

//  构造函数
//  @param name 文件名
//  @param size 文件大小（字节）
    public VideoFile(String name, long size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public long getSize() {
        return size;  // 叶子节点直接返回自身大小
    }

    @Override
    public void add(FileSystemComponent component) {
        // 叶子节点不支持添加操作，抛出异常
        throw new UnsupportedOperationException("叶子节点不支持添加操作");
    }

    @Override
    public void remove(FileSystemComponent component) {
        // 叶子节点不支持删除操作，抛出异常
        throw new UnsupportedOperationException("叶子节点不支持删除操作");
    }

    @Override
    public FileSystemComponent getChild(int index) {
        // 叶子节点没有子节点，抛出异常
        throw new UnsupportedOperationException("叶子节点没有子节点");
    }

    @Override
    public void display(String indent) {
        // 显示视频文件信息，使用电影胶片emoji标识
        System.out.println(indent + "🎬 " + name + " (" + size + " bytes)");
    }
}

// 文件夹类（复合节点）
// 复合节点可以包含其他叶子节点或复合节点，形成树形结构
class Folder implements FileSystemComponent {
    private String name;    // 文件夹名
    private List<FileSystemComponent> children;  // 子组件列表

//     构造函数
//     @param name 文件夹名称
    public Folder(String name) {
        this.name = name;
        this.children = new ArrayList<>();  // 初始化子组件列表
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public long getSize() {
        long totalSize = 0;
        // 递归计算所有子组件的大小之和
        for (FileSystemComponent component : children) {
            totalSize += component.getSize();
        }
        return totalSize;
    }

    @Override
    public void add(FileSystemComponent component) {
        // 向文件夹中添加子组件
        children.add(component);
    }

    @Override
    public void remove(FileSystemComponent component) {
        // 从文件夹中移除子组件
        children.remove(component);
    }

    @Override
    public FileSystemComponent getChild(int index) {
        // 获取指定索引的子组件
        return children.get(index);
    }

    @Override
    public void display(String indent) {
        // 显示文件夹信息，包含总大小
        System.out.println(indent + "📁 " + name + " (总大小: " + getSize() + " bytes)");
        // 递归显示所有子组件，增加缩进以显示层次关系
        for (FileSystemComponent component : children) {
            component.display(indent + "  ");
        }
    }
}

// 客户端演示类
// 演示组合模式在文件系统中的应用
public class FileSystemDemo {
    public static void main(String[] args) {
        // 创建具体的文件对象（叶子节点）
        FileSystemComponent photo1 = new JpgFile("vacation.jpg", 2048);
        FileSystemComponent photo2 = new JpgFile("family.jpg", 4096);
        FileSystemComponent video1 = new VideoFile("tutorial.mp4", 1024000);
        FileSystemComponent video2 = new VideoFile("movie.avi", 2048000);

        // 创建照片文件夹并添加图片文件
        Folder photosFolder = new Folder("照片");
        photosFolder.add(photo1);
        photosFolder.add(photo2);

        // 创建视频文件夹并添加视频文件
        Folder videosFolder = new Folder("视频");
        videosFolder.add(video1);
        videosFolder.add(video2);

        // 创建根文件夹并添加子文件夹
        Folder rootFolder = new Folder("我的文件");
        rootFolder.add(photosFolder);
        rootFolder.add(videosFolder);

        // 显示完整的文件系统结构
        System.out.println("=== 文件系统结构 ===");
        rootFolder.display("");

        // 演示获取不同组件的大小
        System.out.println("\n=== 各组件大小 ===");
        System.out.println("根文件夹大小: " + rootFolder.getSize() + " bytes");
        System.out.println("照片文件夹大小: " + photosFolder.getSize() + " bytes");
        System.out.println("视频文件大小: " + video1.getSize() + " bytes");
    }
}